package main

import (
	"fmt"
	"github.com/gorilla/sessions"
	"github.com/labstack/echo"
	"github.com/labstack/echo-contrib/session"
	echoMiddleware "github.com/labstack/echo/middleware"
	"github.com/labstack/gommon/log"
	"gopkg.in/go-playground/validator.v9"
	"io"
	"maki/config"
	"maki/controller/article"
	"maki/controller/comment"
	"maki/controller/tag"
	"maki/controller/user"
	"maki/middleware"
	"maki/model"
	"maki/search"
	"maki/utils"
	"os"
	"os/signal"
)

type CustomValidator struct {
	validator *validator.Validate
}

func (cv *CustomValidator) Validate(i interface{}) error {
	return cv.validator.Struct(i)
}

func main() {
	//捕获 ctrl-c
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for range c {
			fmt.Println("捕获Ctrl-c，退出服务器")
			model.DB.Close()
			search.Engine.Close()
			os.Exit(0)
		}
	}()

	fmt.Println("echo.Version: ", echo.Version)
	app := echo.New()
	var writer io.Writer
	if config.ServerConfig.Env == config.ServerEnv.DevelopmentMode {
		app.Debug = true
		app.Logger.SetLevel(log.DEBUG)
		writer = os.Stdout
	} else {
		logFile, err := os.OpenFile(config.ServerConfig.LogFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
		if err != nil {
			fmt.Printf(err.Error())
			os.Exit(-1)
		}
		writer = logFile
	}

	// custom app
	app.HTTPErrorHandler = utils.ErrorHandler
	app.Validator = &CustomValidator{validator: validator.New()}

	// Global middleware
	app.Use(echoMiddleware.LoggerWithConfig(echoMiddleware.LoggerConfig{
		Format: `${remote_ip} [${method}] ${status} ${latency_human} ${path} ${bytes_in} ${bytes_out}` + "\n",
		Output: writer,
	}))
	app.Use(echoMiddleware.Recover())
	app.Use(echoMiddleware.Secure())

	store := sessions.NewCookieStore([]byte(config.ServerConfig.TokenSecret))
	store.Options = &sessions.Options{
		Path:     "/",
		MaxAge:   config.ServerConfig.TokenMaxAge,
		Secure:   false,
		HttpOnly: true,
	}
	app.Use(session.Middleware(store))
	app.Use(middleware.SetContextUser)
	app.Routes()

	SigninGroup := app.Group("/api")
	SigninGroup.Use(middleware.SigninRequired)
	{
		SigninGroup.GET("/profile", user.GetProfile)
		SigninGroup.GET("/article", article.GetArticleList(false))
		SigninGroup.GET("/article/:id", article.GetArticle(false))
		SigninGroup.POST("/comment", comment.AddComment)
		SigninGroup.GET("/tags", tag.TagList)
	}

	AdminGroup := app.Group("/api/admin")
	AdminGroup.Use(middleware.SigninRequired)
	{
		AdminGroup.GET("/article", article.GetArticleList(true))
		AdminGroup.GET("/article/:id", article.GetArticle(true))
		AdminGroup.POST("/article", article.AddArticle)
		AdminGroup.PUT("/article/:id", article.UpdateArticle)
		AdminGroup.DELETE("/article/:id", article.DeleteArticle)
	}

	SuperAdminGroup := app.Group("/api/superadmin")
	SuperAdminGroup.Use(middleware.AdminRequired)
	{
		SuperAdminGroup.GET("/reindex", article.ReBuildIndex)
	}

	app.POST("/api/user", user.CreateUser)
	app.POST("/api/login", user.Login)
	app.GET("/api/logout", user.Logout)

	// router.Route(app)
	app.Start(":" + fmt.Sprintf("%d", config.ServerConfig.Port))
}
